﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using BZ.Common;

namespace BZ.Common.FileUtility
{
    /// <summary>
    /// 文本文件处理类
    /// 写入，读取，建立，删除
    /// </summary>
    public class TextFileHelper:IDisposable
    {
        #region 私有

        #region 属性部分
        /// <summary>
        /// 当前状态
        /// </summary>
        protected enum CurStatus { FileClose, FileOpen, ReadyForRead, ReadyForWrite }

        private CurStatus _TextFileStatus;
        /// <summary>
        /// 文件当前状态
        /// </summary>
        protected CurStatus TextFileStatus
        {
            get { return _TextFileStatus; }
        }

        private string _filePath;
        /// <summary>
        /// 路径
        /// </summary>
        protected string FilePath
        {
            get { return _filePath; }
            set { _filePath = value; }
        }

        private Encoding _fileEncode;
        /// <summary>
        /// 文件编码
        /// </summary>
        protected Encoding FileEncode
        {
            get { return _fileEncode; }
            set { _fileEncode = value; }
        }

        private bool _fileIsAppend;
        /// <summary>
        /// 文件是否可追加
        /// </summary>
        protected bool FileIsAppend
        {
            get { return _fileIsAppend; }
            set { _fileIsAppend = value; }
        }

        private FileStream _fileStream;
        /// <summary>
        /// 文件流
        /// </summary>
        protected FileStream TextStream
        {
            get { return _fileStream; }
            set { _fileStream = value; }
        }


        private FileAccess _fileAccess;
        /// <summary>
        /// 接入权限
        /// </summary>
        protected FileAccess TextFileAccess
        {
            get { return _fileAccess; }
            set { _fileAccess = value; }
        }

        /// <summary>
        /// 文件共享接入权限
        /// </summary>
        protected FileShare TextFileShare
        {
            get
            {
                if (TextFileAccess == FileAccess.Read)
                {
                    return FileShare.ReadWrite;
                }
                else
                {
                    return FileShare.Read;
                }
            }
        }

        private StreamWriter _TextFileWriter;
        private StreamReader _TextFileReader;


        private  char[] _ReadBufferArray;
        #endregion

        private TextFileHelper(string filePath, Encoding encodeType, bool isAppend, FileAccess myFileAccess)
        {
            FilePath = filePath;
            FileEncode = encodeType;
            FileIsAppend = isAppend;
            TextFileAccess = isAppend ? FileAccess.Write : myFileAccess;
            _TextFileStatus = CurStatus.FileClose;
            TextStream = null;
            _TextFileWriter = null;
            _TextFileReader = null;
            _ReadBufferArray = null;
        }


        /// <summary>
        /// 获取文件流
        /// </summary>
        /// <param name="myAccess">访问权限</param>
        /// <returns></returns>
        private FileStream GetFileStream()
        {
            FileMode myMode = FileMode.OpenOrCreate;
            if (IsExist && FileIsAppend)
            {
                myMode = FileMode.Append;
            }
            return new FileStream(FilePath, myMode, TextFileAccess, TextFileShare);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="myStr"></param>
        /// <param name="length"></param>
        /// <param name="IsLine"></param>
        /// <returns></returns>
        private ResultInfo ReadFile(out string myStr,int begin, int length, bool IsLine)
        {
            ResultInfo myResult = null;
            myStr = null;
            bool IsSingle = (TextFileStatus == CurStatus.FileClose);//判断是否文件流已经打开,如果没有打开则按单条写入处理

            //单独打开处理文档
            if (IsSingle)
            {
                myResult = OpenFile();
            }

            //获取读取数据的流
            if (myResult == null || myResult.IsSuccess)
            {
                myResult = myResult ?? new ResultInfo(false);
                if (TextStream != null && TextStream.CanRead)
                {
                    try
                    {
                        //判断处理状态
                        if (TextFileStatus == CurStatus.FileOpen)
                        {
                            _TextFileReader = new StreamReader(TextStream, FileEncode);
                            _TextFileStatus = CurStatus.ReadyForRead;
                        }
                        if (TextFileStatus == CurStatus.ReadyForRead && !_TextFileReader.EndOfStream)
                        {
                            if (IsLine == true)
                            {
                                //读取单行
                                myStr = _TextFileReader.ReadLine();
                            }
                            else if (length > 0)
                            {
                                if (_ReadBufferArray == null)
                                {
                                    _ReadBufferArray = new char[length];
                                }
                                //读取指定长度
                                CommonUtility.InitArray<char>(_ReadBufferArray, '\0');
                                _TextFileReader.ReadBlock(_ReadBufferArray, begin, length);
                                myStr = new string(_ReadBufferArray);
                            }
                            else
                            {
                                myStr = _TextFileReader.ReadToEnd();
                            }
                            myResult.IsSuccess = true;
                            myResult.Message = "读取成功。";
                        }
                        else if (TextFileStatus == CurStatus.ReadyForWrite)
                        {
                            myResult.IsSuccess = false;
                            myResult.Message = "当前已经开启写入流，如需读取请关闭后重新初始化或建立其他实例。";
                        }
                        else
                        {
                            if (_TextFileReader.EndOfStream)
                            {
                                throw new Exception("已经到达文件末尾");
                            }
                            myResult.IsSuccess = false;
                            myResult.Message = "读取流未准备好。当前状态为：" + TextFileStatus.ToString();
                        }
                    }
                    catch (Exception ex)
                    {
                        myResult.IsSuccess = false;
                        myResult.Message = ex.Message;
                        //清理全部资源
                        _TextFileStatus = CurStatus.FileClose;
                        CloseFile();
                    }
                }
                else
                {
                    myResult.IsSuccess = false;
                    myResult.Message = TextStream.CanRead ? "文件打开失败。" : "文件不允许读取。";
                }
            }

            //关闭单独文档
            if (IsSingle)
            {
                Dispose();
            }
            return myResult;
        }
        #endregion

        
        /// <summary>
        ///  创建文本文件实例
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="errorMsg">错误信息</param>
        /// <param name="myFileAccess">文件接入方式，缺省readwrite</param>
        /// <param name="encodeType">编码类型，缺省ANSI代码页的编码</param>
        /// <param name="isAppend">是否追加，缺省不追加(不追加情况下不会保存以前的文件内容)</param>
        /// <returns></returns>
        public static TextFileHelper CreateTextFileHelper(string filePath, out string errorMsg,FileAccess myFileAccess = FileAccess.ReadWrite, Encoding encodeType = null, bool isAppend = false)
        {
            errorMsg = string.Empty;
            if (string.IsNullOrEmpty(filePath))
            {
                errorMsg = "文件路径不可为空。";
                return null;
            }
            else
            {
                return new TextFileHelper(filePath, encodeType ?? Encoding.Default, isAppend, myFileAccess);
            }
        }

        /// <summary>
        /// 文件是否存在
        /// </summary>
        public bool IsExist
        {
            get
            {
                return File.Exists(FilePath);
            }
        }

        /// <summary>
        /// 删除当前文件
        /// </summary>
        public ResultInfo Delete()
        {
            ResultInfo myResult = new ResultInfo(false);
            try
            {
                File.Delete(FilePath);
                myResult.IsSuccess = true;
                myResult.Message = "删除完成。";
            }
            catch (Exception ex)
            {
                myResult.IsSuccess = false;
                myResult.Message = ex.Message;
            }
            return myResult;
        }
        
        /// <summary>
        /// 读取指定长度的一段文本,如果文件在之前没有打开，则默认只读取最开始的一段指定长度的文本
        /// </summary>
        /// <param name="myStr"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public ResultInfo ReadBlock(out string myStr, int begin, int length)
        {
            return ReadFile(out myStr, begin, length, false);
        }

        /// <summary>
        /// 读取一行文本,如果文件在之前没有打开，则默认只读取第一行文本
        /// </summary>
        /// <param name="myStr"></param>
        /// <returns></returns>
        public ResultInfo ReadLine(out string myStr)
        {
            return ReadFile(out myStr, 0, 0, true);
        }

        /// <summary>
        /// 读取全部文本
        /// </summary>
        /// <param name="myStr"></param>
        /// <returns></returns>
        public ResultInfo ReadAll(out string myStr)
        {
            return ReadFile(out myStr, 0, 0, false);
        }
        
        /// <summary>
        /// 写入文本
        /// </summary>
        /// <remarks>
        /// 在未打开文件流的时候会自己建立对应的文件流和写入流，在写入对应数据后，自动释放所有资源。
        /// 在当前文件流已经打开情况下，会判断建立写入流，写入后需要手动关闭写入流和文件流。
        /// </remarks>
        /// <param name="IsSingleLine">是否写入成单独行，缺省false</param>
        /// <param name="myStr">需要写入的Format格式</param>
        /// <param name="myObject">参数</param>
        /// <returns></returns>
        public ResultInfo Write(string myStr, params object[] myObject)
        {
            return Write(false, myStr, myObject);
        }
        
        /// <summary>
        /// 写入文本
        /// </summary>
        /// <remarks>
        /// 在未打开文件流的时候会自己建立对应的文件流和写入流，在写入对应数据后，自动释放所有资源。
        /// 在当前文件流已经打开情况下，会判断建立写入流，写入后需要手动关闭写入流和文件流。
        /// </remarks>
        /// <param name="IsSingleLine">是否写入成单独行，缺省false</param>
        /// <param name="myStr">需要写入的Format格式</param>
        /// <param name="myObject">参数</param>
        /// <returns></returns>
        public ResultInfo Write(bool IsSingleLine, string myStr, params object[] myObject)
        {
            return Write(string.Format(myStr, myObject), IsSingleLine);
        }

        /// <summary>
        /// 写入文本
        /// </summary>
        /// <remarks>
        /// 在未打开文件流的时候会自己建立对应的文件流和写入流，在写入对应数据后，自动释放所有资源。
        /// 在当前文件流已经打开情况下，会判断建立写入流，写入后需要手动关闭写入流和文件流。
        /// </remarks>
        /// <param name="myStr">需要写入的串</param>
        /// <param name="IsSingleLine">是否写入成单独行，缺省false</param>
        /// <returns></returns>
        public ResultInfo Write(string myStr, bool IsSingleLine=false)
        {
            ResultInfo myResult = null;
            bool IsSingle = (TextFileStatus == CurStatus.FileClose);//判断是否文件流已经打开,如果没有打开则按单条写入处理

            if (string.IsNullOrEmpty(myStr))
            {
                myResult = new ResultInfo(false, "写入内容为空。");
            }
            else
            {
                //单独打开处理文档
                if (IsSingle)
                {
                    myResult = OpenFile();
                }

                //写入数据
                if (myResult == null || myResult.IsSuccess)
                {
                    myResult = myResult ?? new ResultInfo(false);
                    if (TextStream != null && TextStream.CanWrite)
                    {
                        try
                        {
                            //判断处理状态
                            if (TextFileStatus == CurStatus.FileOpen)
                            {
                                _TextFileWriter = new StreamWriter(TextStream, FileEncode);
                                _TextFileStatus = CurStatus.ReadyForWrite;
                            }
                            
                            if (TextFileStatus == CurStatus.ReadyForWrite)
                            {
                                if (IsSingleLine)
                                {
                                    _TextFileWriter.WriteLine(myStr);
                                }
                                else
                                {
                                    _TextFileWriter.Write(myStr);
                                }
                                _TextFileWriter.Flush();
                                myResult.IsSuccess = true;
                                myResult.Message = "写入成功。";
                            }
                            else if (TextFileStatus == CurStatus.ReadyForRead)
                            {
                                myResult.IsSuccess = false;
                                myResult.Message = "当前已经开启读取流，如需写入请关闭后重新初始化。";
                            }
                            else
                            {
                                myResult.IsSuccess = false;
                                myResult.Message = "写入流未准备好。当前状态为：" + TextFileStatus.ToString();
                            }
                        }
                        catch (Exception ex)
                        {
                            myResult.IsSuccess = false;
                            myResult.Message = ex.Message;

                            //清理全部资源
                            _TextFileStatus = CurStatus.FileClose;
                            CloseFile();
                        }
                    }
                    else
                    {
                        myResult.IsSuccess = false;
                        myResult.Message = TextStream.CanWrite ? "文件打开失败。" : "文件不允许写入。";
                    }
                }

                //关闭单独文档
                if (IsSingle)
                {
                    Dispose();
                }
            }

            return myResult;
        }


        /// <summary>
        /// 建立文件流，需要手动关闭
        /// </summary>
        /// <returns></returns>
        public ResultInfo OpenFile()
        {
            return OpenFile(TextFileAccess, FileIsAppend);
        }

        /// <summary>
        /// 建立文件流，需要手动关闭
        /// </summary>
        /// <returns></returns>
        public ResultInfo OpenFile(FileAccess myFileAccess, bool isAppend)
        {
            ResultInfo myResult = new ResultInfo(false);
            if (TextFileStatus == CurStatus.FileClose || TextStream == null)
            {
                try
                {
                    TextStream = GetFileStream();
                    _TextFileStatus = CurStatus.FileOpen;
                    myResult.IsSuccess = true;
                    myResult.Message = "文件打开完成。";
                }
                catch (Exception ex)
                {
                    myResult.IsSuccess = false;
                    myResult.Message = ex.Message;
                }
            }
            else
            {
                myResult.IsSuccess = true;
                myResult.Message = "文件已经打开。";
            }
            return myResult;
        }

        /// <summary>
        /// 手动关闭文件流
        /// </summary>
        public void CloseFile()
        {
            //读取流处于打开状态
            if ( _TextFileReader != null)
            {
                _TextFileReader.Close();
                _TextFileReader.Dispose();
                _TextFileReader = null;
            }

            //写入流处于打开状态
            if (_TextFileWriter != null)
            {
                _TextFileWriter.Close();
                _TextFileWriter.Dispose();
                _TextFileWriter = null;
            }

            if (TextStream != null)
            {
                TextStream.Close();
                TextStream.Dispose();
                TextStream = null;
            }
            _TextFileStatus = CurStatus.FileClose;
        }

        /// <summary>
        /// 释放文件流资源
        /// </summary>
        public void Dispose()
        {
            CloseFile();
        }

    }
}
